home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1994 December
/
PSL Monthly Shareware CD-ROM (Public Software Library)(December 1994).bin
/
prgmming
/
dos
/
pascal4
/
ovrlay.txt
< prev
next >
Wrap
Text File
|
1990-01-27
|
10KB
|
216 lines
This file explains some of the low-level details of the overlay manager.
It is assumed that the reader is familiar with the documentation provided
in the Turbo Pascal manuals relating to overlays, and with the use of
overlays in general.
Overview
Each overlaid unit has three parts: a static "dispatcher" segment, the
actual overlaid code, and a transient fixup table. The static dispatcher
for each unit is a small code segment that always remains in memory. It
transfers control to the overlay manager if the unit is not currently in
memory, or directly to the unit in the overlay buffer if it is already
present. The overlaid code itself is stored in the application's OVR
file, which is read by the overlay manager each time it must reload an
overlay. The fixup table is also stored in the OVR file, and is used to
correct intersegment references in the overlay code, based on the starting
address of the program.
The Static Dispatcher
Each static dispatcher is a small code segment that's linked into the EXE
file. A unique dispatcher always remains in memory for each overlaid
unit. Whenever you call a procedure in an overlaid unit, you're really
calling a tiny (5 byte) routine in the static dispatcher.
If you have the Turbo Pascal run-time library source, you can find the
"official" documentation for this structure in SE.ASM, which is in INCLUDE.ARC.
Each dispatcher begins with a 32 byte header area, which is laid out as
follows:
type
OverlayHeader = record
{00} ReturnInt : Word;
{02} ReturnOfs : Word;
{04} FileOfs : LongInt;
{08} CodeSize : Word;
{0A} FixupSize : Word;
{0C} EntryPts : Word;
{0E} CodeListNext : Word;
{10} LoadSegment : Word;
{12} Reprieved : Word;
{14} LoadListNext : Word;
{16} EmsPage : Word;
{18} EmsOffset : Word;
{1A} UserData : array [0..2] of Word;
end;
ReturnInt and ReturnOfs are used when RETurning to a unit that has been
booted out by another unit. ReturnInt always contains an INT $3F
instruction. ReturnOfs is a variable field. These are explained in
more detail later.
FileOfs is the offset of the overlaid code segment within the overlay file.
The lowest value this can have is 4 because each overlay file starts with a
four byte signature.
CodeSize specifies the number of bytes of actual code for this unit. To
determine the number of bytes required in the overlay buffer to load the
code of the unit this must be rounded up to the next paragraph.
FixupSize denotes the transient space required while loading the overlay
unit. This must also be rounded up to the next paragraph.
EntryPts specifies the number of 5-byte jump vector entries in the static
dispatcher. Although you might think that this would be the same as the number
of interfaced procedures and functions in the unit, that's not true. The
static dispatcher has an entry for _every_ procedure and function in the
unit, whether it's global or local, interfaced or hidden. The reason
becomes clear when you think about passing procedure parameters -- even a
non-interfaced routine can be called indirectly from outside of the unit,
and the overlay manager must still be informed when to load the code in
such a case. This number thus provides a count of all the routines in a
unit. (It also adds one for the initialization block, if any.)
CodeListNext contains the static segment address of the next unit in a linked
list of all overlaid units in the program. The System unit variable
OvrCodeList contains the segment of the first unit in the list. A value of
zero in CodeListNext marks the end of the list. Segment addresses are
relative to PrefixSeg+$10.
LoadSegment is initially zero. When the overlay manager loads the unit
from disk it stores the segment address where the unit was loaded here.
If the overlay manager unloads the unit from memory, it sets LoadSegment
back to zero.
Reprieved is a flag that is set to 1 when a unit that was on probation is
reprieved.
LoadListNext contains the static segment address of the next unit in a linked
list of all units that are currently loaded in the overlay buffer. The
System unit variable OvrLoadList contains the segment of the first unit in
the list. A value of zero in LoadListNext marks the end of the list.
Segment addresses are absolute.
EmsPage contains the EMS physical-page number where the unit begins when the
overlay file is stored in EMS memory.
EmsOffset contains the byte offset from the beginning of the EMS page when the
overlay file is stored in EMS memory.
UserData is not used by the overlay system as far as anyone has been able to
determine.
The header is followed by a 5-byte "vector" for each procedure and function in
the unit. If the overlay isn't currently loaded, or is on probation, the
vector consist of an INT $3F instruction, followed by one word of data that
specifies the code offset of the routine being called, and an unused
zero-byte. This is the state of the dispatcher when the program is initially
loaded. The INT $3F serves to transfer control to the overlay manager's
code.
If the overlay is already loaded into memory, and is not on probation, the
vector is just a FAR JMP instruction that immediately transfers control to
the real code in the overlay buffer. Returning from an overlaid unit is done
with a simple RETF instruction, just like with normal, non-overlaid routines,
as the FAR JMP does not affect the return address on stack pushed by the
original CALL.
The Overlay File
The overlaid code itself is stored in the application's OVR file, which is
read by the overlay manager each time it must reload an overlay. If EMS
overlays are activated, the OVR file is read entirely into EMS during
initialization, and thereafter overlays are transferred to the overlay
buffer from EMS rather than from disk.
The transient fixup tables are also stored in the OVR file, immediately
following the code for each unit. The overlay manager reads this
information into the overlay buffer each time an overlay is loaded. Fixup
information is used to correct intersegment references in the overlay
code, based on the starting address of the program. This information is
"transient" because it's used only when the overlay is being loaded; it
doesn't retain space in the overlay buffer thereafter.
Loading an Overlay
When a call is made to a function or procedure in an overlay that is not
present in memory, the INT $3F instruction in the dispatcher transfers
control to the overlay manager, which does the following:
1. Finds space for the overlay (perhaps by booting out other overlays).
2. Loads the required overlay code into memory and updates LoadSegment in the
header.
3. Changes the INT $3F instructions in the dispatcher to FAR JMPs. The
code offset word following the INT $3F is used here to create the jump
instruction.
4. Adjusts the return address of the INT instruction. If left alone, this
would return to the third byte of the FAR JMP instruction. It's adjusted
to return to the beginning of the FAR JMP.
5. Returns to the dispatcher. This tranfers control to the FAR JMP code,
which in turn jumps to the requested procedure.
Removing an Overlay
Special precautions are taken when an overlaid unit is to be removed from
the overlay buffer. Without this preparation, when you are about to
return to an overlaid unit that is no longer in the overlay buffer, maybe
because you call one overlay from another, the return address on the stack
would point to the physical address where the CALL instruction USED TO BE.
This clearly won't work. Something must be done to avoid this situation,
and that's where ReturnInt and ReturnOfs enter the picture.
When a unit is to be moved or removed from the overlay buffer, the overlay
manager traverses the stack, looking for return addresses that point into
that unit. Since a unit is not likely to be reloaded at the same address it
came from, all return addresses into the unit must be changed. It does this
by jumpin